/* Copyright 2001,2002,2003 NAH6 BV
 * All Rights Reserved
 *
 *  $Header: /var/lib/cvs/secphone/ui/misc/debug.cpp,v 1.7 2003/11/21 16:12:58 itsme Exp $
 *
 *
 * implement debug/error logging services
 *
 * To enable debugging call one or more of the DebugXXX functions
 *
 * the release version of CryptoPhone does not contain any debug logging functions,
 * the 'removedebug.pl' script is used to strip out all code related to that.
 *
 */

#include <windows.h>

#include "debug.h"        // declarations for this file.
#include "stringutils.h"  // for ToString etc.

#define DBG_OUTPUTDEBUGSTRING 1
#define DBG_MESSAGEBOX        2
#define DBG_DEBUGWINDOW       4
#define DBG_LOGFILE           8

#ifdef _WIN32_WCE
//  define these for wince use
#define DBG_WCHAROUTPUT (DBG_OUTPUTDEBUGSTRING|DBG_MESSAGEBOX|DBG_DEBUGWINDOW)
#define DBG_CHAROUTPUT (DBG_LOGFILE)
#else
#ifdef _UNICODE
//  define these for unicode desktop use
#define DBG_WCHAROUTPUT (DBG_OUTPUTDEBUGSTRING|DBG_MESSAGEBOX|DBG_DEBUGWINDOW)
#define DBG_CHAROUTPUT (DBG_LOGFILE)
#else
//  define these for non unicode desktop use
#define DBG_WCHAROUTPUT (0)
#define DBG_CHAROUTPUT (DBG_LOGFILE|DBG_OUTPUTDEBUGSTRING|DBG_MESSAGEBOX|DBG_DEBUGWINDOW)
#endif
#endif

int g_debugOutputFlags;
char g_logfilename[MAX_PATH+1];
HANDLE g_log_mutex;
CDebugWindow *g_debugWindow;

#define MAX_DEBUG_LENGTH 16384

void DebugSetLogfile(const char *filename)
{
    g_log_mutex= CreateMutex(NULL, false, NULL);
    strncpy(g_logfilename, filename, MAX_PATH);
    g_logfilename[MAX_PATH]=0;
    g_debugOutputFlags |= DBG_LOGFILE;
}
void DebugRegisterWindow(CDebugWindow *wnd)
{
    g_debugWindow= wnd;

    g_debugOutputFlags |= DBG_DEBUGWINDOW;
}
void DebugMessagebox()
{
    g_debugOutputFlags |= DBG_MESSAGEBOX;
}
void DebugOutputDebugString()
{
    g_debugOutputFlags |= DBG_OUTPUTDEBUGSTRING ;
}
void wdebugoutput(const WCHAR *wbuf)
{
#if DBG_WCHAROUTPUT&DBG_OUTPUTDEBUGSTRING
    if (g_debugOutputFlags&DBG_OUTPUTDEBUGSTRING) {
        int len= _tcslen(wbuf);
        for (int i= 0 ; i<len ; i+=512)
        {
            WCHAR smallbuf[513];
            wcsncpy(smallbuf, wbuf+i, 512);
            smallbuf[512]= 0;
            OutputDebugString(smallbuf);
        }
    }
#endif
#if DBG_WCHAROUTPUT&DBG_MESSAGEBOX
    if (g_debugOutputFlags&DBG_MESSAGEBOX) {
        MessageBox(0,wbuf,L"debug",0);
    }
#endif
#if DBG_WCHAROUTPUT&DBG_DEBUGWINDOW
    if (g_debugOutputFlags&DBG_DEBUGWINDOW) {
        g_debugWindow->appendString(wbuf);
    }
#endif
}
void debugoutput(const char *buf)
{
#if DBG_CHAROUTPUT&DBG_OUTPUTDEBUGSTRING
    if (g_debugOutputFlags&DBG_OUTPUTDEBUGSTRING) {
        int len= (int)strlen(buf);
        for (int i= 0 ; i<len ; i+=512)
        {
            char smallbuf[513];
            strncpy(smallbuf, buf+i, 512);
            smallbuf[512]= 0;
            OutputDebugString(smallbuf);
        }
    }
#endif
#if DBG_CHAROUTPUT&DBG_MESSAGEBOX
    if (g_debugOutputFlags&DBG_MESSAGEBOX) {
        MessageBox(0,buf,"debug",0);
    }
#endif
#if DBG_CHAROUTPUT&DBG_DEBUGWINDOW
    if (g_debugOutputFlags&DBG_DEBUGWINDOW) {
        g_debugWindow->appendString(buf);
    }
#endif
    if (g_debugOutputFlags&DBG_LOGFILE) {
        WaitForSingleObject(g_log_mutex, INFINITE);
        FILE *f= fopen(g_logfilename, "a+");
        fputs(buf, f);
        fclose(f);
        ReleaseMutex(g_log_mutex);
    }
}



void vwdebug(const WCHAR *msg, va_list ap)
{
    WCHAR *wbuf= new WCHAR[MAX_DEBUG_LENGTH];
    _vsnwprintf(wbuf, MAX_DEBUG_LENGTH, msg, ap);
    if (g_debugOutputFlags&DBG_CHAROUTPUT) {
        debugoutput(ToString(wbuf).c_str());
    }
    wdebugoutput(wbuf);
    delete[] wbuf;
}

void vdebug(const char *msg, va_list ap)
{
    char *buf = new char[MAX_DEBUG_LENGTH];
    _vsnprintf(buf, MAX_DEBUG_LENGTH, msg, ap);
    if (g_debugOutputFlags&DBG_WCHAROUTPUT) {
        wdebugoutput(ToWString(buf).c_str());
    }
    debugoutput(buf);
    delete[] buf;
}
void wdebug(const WCHAR *msg, ...)
{
    va_list ap;

    va_start(ap, msg);
    vwdebug(msg, ap);
    va_end(ap);
}
void debug(const char *msg, ...)
{
    va_list ap;

    va_start(ap, msg);
    vdebug(msg, ap);
    va_end(ap);
}

void verror(DWORD dwErrorCode, const char *msg, va_list ap)
{
    debug("ERROR: ");

    vdebug(msg, ap);

    // todo: make this charsize independent
    TCHAR* msgbuf;
    int rc= FormatMessage(
            FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
            NULL, dwErrorCode, 0, (TCHAR*) &msgbuf, 0, NULL);
    if (rc)
        debug(" - %ls\n", msgbuf);
    else
        debug(" - UNKNOWNERROR: 0x%08lx\n", dwErrorCode);
    LocalFree(msgbuf);
}
void error(DWORD dwErrorCode, const char *msg, ...)
{
    va_list ap;
    va_start(ap, msg);
    verror(dwErrorCode, msg, ap);
    va_end(ap);
}

void error(const char *msg, ...)
{
    va_list ap;
    va_start(ap, msg);
    verror(GetLastError(), msg, ap);
    va_end(ap);
}

#if 0
//  _WIN32_WCE
void ceerror(const char *msg, ...)
{
    va_list ap;
    va_start(ap, msg);
    verror(CeRapiGetError() || CeGetLastError(), msg, ap);
    va_end(ap);
}
#endif
